﻿// facecat_cpp.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "facecat_cpp.h"
#include <wx/wx.h>
#include "Win32\\wxWidgetsPaint.h"
#include "Win32\\WinHost.h"
#include "MainFrame.h"
#include "wx/dcbuffer.h"
#include <wx/timer.h>

class MyApp : public wxApp {
public:
    virtual bool OnInit();
};

class MyFrame : public wxFrame {
public:
	/**
	* 设备对接
	*/
	WinHost* m_host;
	/**
	* 公共方法库
	*/
	FCNative* m_native;
	/*
	* 绘图对象
	*/
	wxWidgetsPaint* m_paint;
	/*
	* wxWidgets输入框
	*/
	wxTextCtrl* m_textBox;
	/**
	* 虚拟输入框
	*/
	FCView* m_editingTextBox;
	wxTimer* m_timer;
public:
    MyFrame();
	virtual ~MyFrame();
	void onLoad();
	void OnLeftDown(wxMouseEvent& event);
	void OnLeftUp(wxMouseEvent& event);
	void OnRightDown(wxMouseEvent& event);
	void OnRightUp(wxMouseEvent& event);
	void OnLeftDClick(wxMouseEvent& event);
	void OnMouseWheel(wxMouseEvent& event);
	void OnMotion(wxMouseEvent& event);
	void OnPaint(wxPaintEvent& event);
	void OnSize(wxSizeEvent& event);
	void OnEraseBackGround(wxEraseEvent& event);
	void OnTimer(wxTimerEvent& event);
	/**
	 * 显示文本框
	 */
	void showTextBox(FCView* view, FCView* lastView);
	/**
	 * 隐藏文本框
	 */
	void hideTextBox(FCView* view);
};

IMPLEMENT_APP(MyApp)

bool MyApp::OnInit() {
    MyFrame* frame = new MyFrame();
    frame->Show(true);
	frame->onLoad();
    return true;
}

MyFrame::MyFrame()
    : wxFrame(nullptr, wxID_ANY, "FaceCat wxWidgets") {
    // 设置窗口大小
    SetClientSize(800, 600);
	m_timer = 0;
	m_host = 0;
	m_native = 0;
	m_paint = 0;
	m_textBox = 0;
	m_editingTextBox = 0;
}

MyFrame::~MyFrame() {
	if (m_timer) {
		m_timer->Stop();
		delete m_timer;
		m_timer = 0;
	}
	if (m_native) {
		delete m_native;
		m_native = 0;
	}
	m_host = 0;
	m_native = 0;
	m_paint = 0;
	m_textBox = 0;
	m_editingTextBox = 0;
}

void MyFrame::onLoad() {
	m_native = new FCNative;
	String appPath = FCTran::stringToString(FCTran::getAppPath());
	m_native->setResourcePath(appPath + L"\\");
	m_paint = new wxWidgetsPaint();
	m_native->setPaint(m_paint);
	WinHost* host = new WinHost;
	host->setNative(m_native);
	m_native->setHost(host);
	host->m_view = this;
	m_host = host;
	MainFrame* mainFrame = new MainFrame;
	mainFrame->setNative(m_native);
	mainFrame->loadFile(appPath + L"\\MainFrame2.xml", 0);
	wxWindowID tID = this->GetId();
	Bind(wxEVT_LEFT_DOWN, &MyFrame::OnLeftDown, this, tID);
	Bind(wxEVT_LEFT_UP, &MyFrame::OnLeftUp, this, tID);
	Bind(wxEVT_RIGHT_DOWN, &MyFrame::OnRightDown, this, tID);
	Bind(wxEVT_RIGHT_DOWN, &MyFrame::OnRightUp, this, tID);
	Bind(wxEVT_LEFT_DCLICK, &MyFrame::OnLeftDClick, this, tID);
	Bind(wxEVT_LEFT_DOWN, &MyFrame::OnLeftDown, this, tID);
	Bind(wxEVT_MOTION, &MyFrame::OnMotion, this, tID);
	Bind(wxEVT_MOUSEWHEEL, &MyFrame::OnMouseWheel, this, tID);
	Bind(wxEVT_PAINT, &MyFrame::OnPaint, this, tID);
	Bind(wxEVT_SIZE, &MyFrame::OnSize, this, tID);
	Bind(wxEVT_ERASE_BACKGROUND, &MyFrame::OnEraseBackGround, this, tID);

	m_textBox = new wxTextCtrl(this, wxID_ANY, "", wxDefaultPosition, wxDefaultSize);
	m_textBox->Hide();
	FCSize newSize = { GetSize().GetWidth(), GetSize().GetHeight() - 40 };
	m_native->setSize(newSize);
	m_native->update();

	m_timer = new wxTimer(this, 1);
	Bind(wxEVT_TIMER, &MyFrame::OnTimer, this, 1);
	m_timer->Start(10);
}

void MyFrame::OnLeftDown(wxMouseEvent& event) {
	wxPoint pos = event.GetPosition();
	FCPoint pt = {pos.x, pos.y };
	m_host->setTouchPoint(pt);
	FCTouchInfo touchInfo;
	touchInfo.m_clicks = 1;
	touchInfo.m_firstTouch = true;
	touchInfo.m_firstPoint = pt;
	FCView* lastFocusedView = m_native->getFocusedView();
	m_native->onTouchDown(touchInfo);
	FCView* focusedView = m_native->getFocusedView();
	if (dynamic_cast<FCTextBox*>(focusedView)) {
		showTextBox(focusedView, lastFocusedView);
	}
	else {
		hideTextBox(focusedView);
	}
}

void MyFrame::OnLeftUp(wxMouseEvent& event) {
	wxPoint pos = event.GetPosition();
	FCPoint pt = {pos.x, pos.y };
	m_host->setTouchPoint(pt);
	FCTouchInfo touchInfo;
	touchInfo.m_clicks = 1;
	touchInfo.m_firstTouch = true;
	touchInfo.m_firstPoint = pt;
	m_native->onTouchUp(touchInfo);
}

void MyFrame::OnRightDown(wxMouseEvent& event) {
	wxPoint pos = event.GetPosition();
	FCPoint pt = {pos.x, pos.y };
	m_host->setTouchPoint(pt);
	FCTouchInfo touchInfo;
	touchInfo.m_clicks = 1;
	touchInfo.m_secondTouch = true;
	touchInfo.m_secondPoint = pt;
	FCView* lastFocusedView = m_native->getFocusedView();
	m_native->onTouchDown(touchInfo);
	FCView* focusedView = m_native->getFocusedView();
	if (dynamic_cast<FCTextBox*>(focusedView)) {
		showTextBox(focusedView, lastFocusedView);
	}
	else {
		hideTextBox(focusedView);
	}
}

void MyFrame::OnRightUp(wxMouseEvent& event) {
	wxPoint pos = event.GetPosition();
	FCPoint pt = {pos.x, pos.y };
	m_host->setTouchPoint(pt);
	FCTouchInfo touchInfo;
	touchInfo.m_clicks = 1;
	touchInfo.m_secondTouch = true;
	touchInfo.m_secondPoint = pt;
	m_native->onTouchUp(touchInfo);
}

void MyFrame::OnLeftDClick(wxMouseEvent& event) {
	wxPoint pos = event.GetPosition();
	FCPoint pt = {pos.x, pos.y };
	m_host->setTouchPoint(pt);
	FCTouchInfo touchInfo;
	touchInfo.m_clicks = 2;
	touchInfo.m_firstTouch = true;
	touchInfo.m_firstPoint = pt;
	m_native->onTouchDown(touchInfo);
}

void MyFrame::OnMouseWheel(wxMouseEvent& event) {
	wxPoint pos = event.GetPosition();
	FCPoint pt = {pos.x, pos.y };
	m_host->setTouchPoint(pt);
	FCTouchInfo touchInfo;
	touchInfo.m_clicks = 0;
	touchInfo.m_firstTouch = false;
	touchInfo.m_firstPoint = pt;
	touchInfo.m_delta = event.GetWheelRotation();
	m_native->onTouchWheel(touchInfo);
}

void MyFrame::OnMotion(wxMouseEvent& event) {
	wxPoint pos = event.GetPosition();
	FCPoint pt = {pos.x, pos.y };
	m_host->setTouchPoint(pt);
	FCTouchInfo touchInfo;
	if (m_native->m_touchDownView) {
		touchInfo.m_clicks = 1;
		touchInfo.m_firstTouch = true;
	}
	touchInfo.m_firstPoint = pt;
	m_native->onTouchMove(touchInfo);
}

void MyFrame::OnPaint(wxPaintEvent& event) {
	if (m_host) {
		wxWidgetsPaint* wPaint = dynamic_cast<wxWidgetsPaint*>(m_native->getPaint());
		wxBufferedPaintDC dc(this);
		dc.SetBrush(*wxWHITE_BRUSH);
		dc.Clear();
		wPaint->m_dc = &dc;
		FCRect drawRect = { 0, 0, m_native->getSize().cx, m_native->getSize().cy};
		m_host->onPaint(0, drawRect);
	}
}

void MyFrame::OnSize(wxSizeEvent& event) {
	if (m_host) {
		double scaleFactorX = 1, scaleFactorY = 1;
		m_paint->getScaleFactor(&scaleFactorX, &scaleFactorY);
		FCSize newSize = {GetSize().GetWidth() / scaleFactorX, (GetSize().GetHeight() - 40) / scaleFactorY };
		m_native->setSize(newSize);
		m_native->update();
	}
	this->Refresh();
}

void MyFrame::OnEraseBackGround(wxEraseEvent& event) {
}

void MyFrame::showTextBox(FCView* view, FCView* lastView) {
	if (m_textBox && m_editingTextBox) {
		if (lastView && lastView != view && dynamic_cast<FCTextBox*>(lastView)) {
			lastView->setText(m_textBox->GetValue().ToStdWstring().c_str());
			lastView->invalidate();
		}
	}
	m_editingTextBox = view;
	int clX = m_native->clientX(view);
	int clY = m_native->clientY(view);
	double scaleFactorX = 0, scaleFactorY = 0;
	m_paint->getScaleFactor(&scaleFactorX, &scaleFactorY);
	m_textBox->SetSize(view->getWidth() * scaleFactorX, view->getHeight() * scaleFactorY);
	wxPoint position(clX * scaleFactorX, clY * scaleFactorY);
	m_textBox->SetPosition(position);
	m_textBox->SetValue(FCTran::StringTostring(view->getText()).c_str());
	m_textBox->SetBackgroundColour(m_paint->getWxColor(view->getBackColor()));
	m_textBox->SetForegroundColour(m_paint->getWxColor(view->getTextColor()));

	FCFont* font = view->getFont();
	String fontFamily = font->m_fontFamily;
	if (fontFamily == L"Default") {
		fontFamily = MyColor::getSystemFont();
	}
	float fontSize = font->m_fontSize;
	if (scaleFactorX != 1 || scaleFactorY != 1) {
		fontSize = min(scaleFactorX, scaleFactorY) * fontSize;
	}
	wxFont wFont((int)fontSize - 3, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
	m_textBox->SetFont(wFont);
	m_textBox->Show();
	m_textBox->SetFocus();
}

void MyFrame::hideTextBox(FCView* view) {
	if (m_textBox && m_editingTextBox) {
		m_editingTextBox->setText(m_textBox->GetValue().ToStdWstring().c_str());
		m_textBox->Hide();
		m_editingTextBox = 0;
		m_native->invalidate();
	}
}

void MyFrame::OnTimer(wxTimerEvent& event) {
	if (m_host) {
		m_host->onTimer();
	}
}